<template>
  <Dialog v-model="dialogVisible" :title="dialogTitle" width="1100px">
    <el-form
      :model="formData"
      ref="formRef"
      :rules="formRules"
      vloading="formLoading"
      label-width="auto"
    >
      <el-row>
        <el-col :span="12">
          <el-form-item label="老人姓名" prop="elderId">
            <el-input
              v-model="formData.elder.name"
              :clearable="true"
              :disabled="true"
              class="mr-1"
            />
            <el-button @click="clickChooseElder" v-if="isEdit">选择老人</el-button>
          </el-form-item>
        </el-col>

        <el-col :span="12">
          <el-form-item label="床位名称" prop="bedInfoId">
            <el-input
              v-model="formData.bedInfo.bedName"
              :clearable="true"
              :disabled="true"
              class="mr-1"
            />
            <el-button @click="clickChooseBed" v-if="isEdit">选择床位</el-button>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="12">
          <el-form-item label="餐饮套餐名称" prop="restaurant.comboName">
            <el-input
              v-model="restaurantComboName"
              :clearable="true"
              :disabled="true"
              class="mr-1"
            />
            <el-button @click="clickChooseRestaurantCombo" v-if="isEdit">选择餐饮套餐</el-button>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="护理计划名称" prop="nurse.planName">
            <el-input v-model="nursePlanName" :clearable="true" :disabled="true" class="mr-1" />
            <el-button @click="clickChooseNursePlan" v-if="isEdit">选择护理计划</el-button>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="12">
          <el-form-item label="入住开始时间" prop="beginTime">
            <el-date-picker
              v-model="formData.beginTime"
              :placeholder="isEdit ? '请输入入住开始时间' : ''"
              :clearable="true"
              value-format="YYYY-MM-DD HH:mm:ss"
              :disabled="!isEdit"
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="入住预计结束时间" prop="endTime">
            <el-date-picker
              v-model="formData.endTime"
              :placeholder="isEdit ? '请输入入住预计结束时间' : ''"
              :clearable="true"
              value-format="YYYY-MM-DD HH:mm:ss"
              :disabled="!isEdit"
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="12">
          <el-form-item label="支付方式" prop="payType">
            <el-select v-model="formData.payType" :disabled="!isEdit">
              <el-option
                v-for="dict in getIntDictOptions(DICT_TYPE.FEE_PAY_TYPE)"
                :key="dict.value"
                :label="dict.label"
                :value="dict.value"
              />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="应收费用" prop="receivableFee">
            <el-input v-model="formData.receivableFee" disabled />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="12">
          <el-form-item label="减免费用" prop="reductionFee">
            <el-input
              v-model="formData.reductionFee"
              :placeholder="isEdit ? '请输入减免费用' : ''"
              :clearable="true"
              :disabled="!isEdit"
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="实交费用" prop="checkInFee">
            <el-input v-model="formData.checkInFee" disabled />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <el-form-item>
      <el-button @click="clickAddFee">添加费用</el-button>
      <el-button @click="clickDeleteFee">删除费用</el-button>
    </el-form-item>
    <Table
      :columns="columns"
      :adaptive="true"
      :data="formData.fees"
      save-key="ElderCheckInEdit"
      :row-style="rowStyle"
      @row-click="handleRowClick"
      @row-dblclick="handleTableDblclick"
      class="h-[230px]"
    >
      <template #remark="{ row }">
        <el-input class="!w-170px" v-model="row.remark" :disabled="!isEdit" />
      </template>
    </Table>
    <template #footer>
      <el-button type="primary" :disabled="formLoading" @click="submitForm">确 定</el-button>
      <el-button @click="dialogVisible = false">取 消</el-button>
    </template>
  </Dialog>
  <ElderInfoSelect ref="elderInfoRef" @row-dblclick="handleSelectElderInfo" />
  <BedInfoSelect ref="bedInfoRef" @select-value="handleSelectBedInfo" />
  <NursePlanSelect ref="nursePlanRef" @select-value="handleSelectNursePlan" />
  <RestaurantComboSelect ref="restaurantComboRef" @select-value="handleSelectRestaurantCombo" />
  <FeeCategorySelect ref="feeCategoryRef" @select-value="handleSelectFeeCategory" />
</template>
<script setup name="ElderCheckInEdit" lang="ts">
import * as ElderCheckInApi from '@/api/elder/checkIn'
import * as FeeCatetoryApi from '@/api/fee/feeCategory'
import * as NursePlanApi from '@/api/nurse/nursePlan'
import FeeCategorySelect from '@/views/fee/feeCategory/FeeCategorySelect.vue'
import ElderInfoSelect from '@/views/elder/elderInfo/ElderInfoSelect.vue'
import BedInfoSelect from '@/views/bed/bedInfo/BedInfoSelect.vue'
import NursePlanSelect from '@/views/nurse/nursePlan/NursePlanSelect.vue'
import RestaurantComboSelect from '@/views/restaurant/restaurantRecipe/RestaurantComboSelect.vue'
import * as ElderCheckInModel from '@/model/elder/register/ElderCheckIn'
import * as ElderCheckInFeeModel from '@/model/elder/register/ElderCheckInFee'
import * as NursePlanModel from '@/model/nurse/plan/NursePlan'
import * as NursePlanDetailModel from '@/model/nurse/plan/NursePlanDetail'
import * as NurseItemmModel from '@/model/nurse/item/NurseItem'
import { getKeyList } from '@pureadmin/utils'
import { FeeChargeTypeEnum, NursePlanExecTypeEnum, ElderCheckInStatusEnum } from '@/utils/constants'
import * as formatTime from '@/utils/formatTime'
import dayjs from 'dayjs'
import { round } from 'lodash-es'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
interface ElderCheckInFeeEdit extends ElderCheckInFeeModel.ElderCheckInFee {
  feeCategory: { categoryName: string }
  operateType: string
}
interface NursePlanDetail extends NursePlanDetailModel.NursePlanDetail {
  item: NurseItemmModel.NurseItem
}
interface NursePlan extends NursePlanModel.NursePlan {
  details: NursePlanDetail[]
}
interface ElderCheckInEdit extends ElderCheckInModel.ElderCheckIn {
  elder: { name: string }
  nursePlan: NursePlan
  restaurantCombo: { comboName: string; chargeType: number; price: number }
  bedInfo: { bedName: string; chargeType: number; price: number }
  receivableFee: number
  fees: ElderCheckInFeeEdit[]
}
const feeCategoryRef = ref()
const elderInfoRef = ref()
const bedInfoRef = ref()
const nursePlanRef = ref()
const restaurantComboRef = ref()
const dialogTitle = ref('')
const dialogVisible = ref(false)
const formRef = ref()
const formLoading = ref(false)
const isEdit = ref(true)
let formType = ''
const { t } = useI18n()
const message = useMessage()
const nursePlanName = computed(() => {
  if (formData.value.nursePlan == null) return ''
  else return formData.value.nursePlan.planName
})
const restaurantComboName = computed(() => {
  if (formData.value.restaurantCombo == null) return ''
  else return formData.value.restaurantCombo.comboName
})

const formData = ref<ElderCheckInEdit>({
  id: undefined,
  checkInNo: '',
  elderId: 0,
  nursePlanId: 0,
  restaurantComboId: 0,
  bedInfoId: 0,
  elder: { name: '' },
  nursePlan: { id: undefined, planName: '', planIntroduction: '', details: [] },
  restaurantCombo: { comboName: '', chargeType: 1, price: 0 },
  bedInfo: { bedName: '', chargeType: 1, price: 0 },
  beginTime: undefined,
  endTime: undefined,
  receivableFee: 0,
  checkInFee: 0,
  reductionFee: 0,
  status: ElderCheckInStatusEnum.TO_BE_CHECK_IN,
  payType: 1,
  fees: []
})
const formRules = reactive({
  elderId: [{ required: true, message: '请输入老人姓名', trigger: 'change' }],
  bedInfoId: [{ required: true, message: '请选择床位', trigger: 'change' }],
  beginTime: [{ required: true, message: '请选择入住开始时间', trigger: 'blur' }],
  endTime: [{ required: true, message: '请选择入住预计结束时间', trigger: 'blur' }]
})
const tableCurrentRow = ref()
const columns = [
  {
    label: '费用类别名称',
    prop: 'feeCategory.categoryName'
  },
  {
    label: '费用',
    prop: 'fee'
  },
  {
    label: '备注',
    prop: 'remark',
    slot: 'remark'
  }
]

watch(
  [
    () => formData.value.beginTime,
    () => formData.value.endTime,
    () => formData.value.bedInfoId,
    () => formData.value.nursePlanId,
    () => formData.value.restaurantComboId
  ],
  ([newBeginTime, newEndTime, newBedInfoId, newNursePlanId, newRestaurantComboId]) => {
    if (newBeginTime == undefined || newEndTime == undefined) return
    const beginTime = new Date(newBeginTime)
    const endTime = new Date(newEndTime)

    let receivableFee = 0
    if (newBedInfoId != null && newBedInfoId != 0) {
      let bedFee = 0
      if (formData.value.bedInfo.chargeType == FeeChargeTypeEnum.DAY) {
        const day = formatTime.betweenDay(beginTime, endTime)
        if (day > 0) {
          bedFee += formData.value.bedInfo.price * day
        }
      } else {
        const month = dayjs(endTime).diff(beginTime, 'M')
        const day = -dayjs(beginTime).add(month, 'M').diff(endTime, 'd')
        if (month > 0) {
          bedFee += formData.value.bedInfo.price * month
        }
        if (day > 0) {
          bedFee += (formData.value.bedInfo.price / 30) * day
        }
      }
      receivableFee += round(bedFee, 2)
      formData.value.fees.forEach((fee) => {
        if (fee.feeCategoryId == 1) fee.fee = round(bedFee, 2)
      })
    }
    if (newNursePlanId != null && newNursePlanId != 0) {
      let nurseFee = 0
      formData.value.nursePlan.details.forEach((detail) => {
        nurseFee += calcNurseDetailFee(detail, beginTime, endTime)
      })
      receivableFee += round(nurseFee, 2)
      formData.value.fees.forEach((fee) => {
        if (fee.feeCategoryId == 2) fee.fee = round(nurseFee, 2)
      })
    }
    if (newRestaurantComboId != null && newRestaurantComboId != 0) {
      let restaurantFee = 0
      if (formData.value.restaurantCombo.chargeType == FeeChargeTypeEnum.DAY) {
        const day = formatTime.betweenDay(beginTime, endTime)
        if (day > 0) {
          restaurantFee += formData.value.restaurantCombo.price * day
        }
      } else {
        const month = dayjs(endTime).diff(beginTime, 'M')
        const day = -dayjs(beginTime).add(month, 'M').diff(endTime, 'd')
        if (month > 0 || day > 0) {
          restaurantFee += formData.value.restaurantCombo.price * month
          restaurantFee += (formData.value.restaurantCombo.price / 30) * day
        }
      }
      receivableFee += round(restaurantFee, 2)
      formData.value.fees.forEach((fee) => {
        if (fee.feeCategoryId == 3) fee.fee = round(restaurantFee, 2)
      })
    }
    formData.value.receivableFee = receivableFee
  }
)

watch(
  [() => formData.value.receivableFee, () => formData.value.reductionFee],
  ([newReceivableFee, newReductionFee]) => {
    formData.value.checkInFee = Math.max(newReceivableFee - newReductionFee, 0)
  }
)
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
  dialogVisible.value = true
  dialogTitle.value = t('action.' + type)
  formType = type
  resetForm()
  // 修改时，设置数据
  if (id) {
    formLoading.value = true
    try {
      formData.value = await ElderCheckInApi.get(id)
      isEdit.value = formData.value.status == ElderCheckInStatusEnum.TO_BE_CHECK_IN
    } finally {
      formLoading.value = false
    }
  } else {
    const firstFees = await FeeCatetoryApi.getFirstFee()
    firstFees.forEach((fee) => {
      formData.value.fees.push({
        id: undefined,
        checkInId: undefined,
        feeCategoryId: fee.id,
        feeCategory: { categoryName: fee.categoryName },
        fee: fee.fee,
        remark: '',
        operateType: 'new'
      })
    })
  }
}
defineExpose({ open }) // 提供 open 方法，用于打开弹窗

/** 重置表单 */
const resetForm = () => {
  formData.value = {
    id: undefined,
    checkInNo: '',
    elderId: 0,
    nursePlanId: 0,
    restaurantComboId: 0,
    bedInfoId: 0,
    elder: { name: '' },
    nursePlan: { id: undefined, planName: '', planIntroduction: '', details: [] },
    restaurantCombo: { comboName: '', chargeType: 1, price: 0 },
    bedInfo: { bedName: '', chargeType: 1, price: 0 },
    beginTime: undefined,
    endTime: undefined,
    receivableFee: 0,
    checkInFee: 0,
    reductionFee: 0,
    status: 1,
    payType: 1,
    fees: []
  }
  formRef.value?.resetFields()
  isEdit.value = true
}

const emit = defineEmits(['success'])
/** 提交表单 */
const submitForm = async () => {
  // 校验表单
  if (!formRef) return
  const valid = await formRef.value.validate()
  if (!valid) return
  // 提交请求
  formLoading.value = true
  try {
    const data = formData.value as unknown as ElderCheckInEdit
    if (formType === 'create') {
      await ElderCheckInApi.create(data)
      message.success(t('common.createSuccess'))
    } else {
      await ElderCheckInApi.update(data)
      message.success(t('common.updateSuccess'))
    }
    dialogVisible.value = false
    // 发送操作成功的事件
    emit('success')
  } finally {
    formLoading.value = false
  }
  emit('success')
}

/** table行的style的回调方法 */
const rowStyle = ({ row }) => {
  if (row?.operateType == 'delete') {
    return { display: 'none' }
  } else return {}
}

/** table行点击事件 */
const handleRowClick = (row) => {
  tableCurrentRow.value = row
}

const clickChooseElder = () => {
  elderInfoRef.value.open()
}

const clickChooseNursePlan = () => {
  nursePlanRef.value.open()
}

const clickChooseRestaurantCombo = () => {
  restaurantComboRef.value.open()
}

const clickChooseBed = () => {
  bedInfoRef.value.open()
}

const clickAddFee = () => {
  feeCategoryRef.value.open()
}

const handleSelectElderInfo = (selectElderInfo) => {
  formData.value.elder.name = selectElderInfo.name
  formData.value.elderId = selectElderInfo.id
}

const handleSelectBedInfo = (selectBedInfo) => {
  formData.value.bedInfo = selectBedInfo
  formData.value.bedInfoId = selectBedInfo.id
  const existsFeeCategoryIds = getKeyList(formData.value.fees, 'feeCategoryId')
  if (existsFeeCategoryIds.indexOf(1) < 0) {
    formData.value.fees.push({
      id: undefined,
      checkInId: formType === 'create' ? undefined : formData.value.id,
      feeCategoryId: 1,
      feeCategory: { categoryName: '床位费' },
      fee: 0,
      remark: '',
      operateType: 'new'
    })
  }
}

const handleSelectNursePlan = async (selectNursePlan) => {
  formData.value.nursePlan = await NursePlanApi.get(selectNursePlan.id)
  formData.value.nursePlanId = selectNursePlan.id
  const existsFeeCategoryIds = getKeyList(formData.value.fees, 'feeCategoryId')
  if (existsFeeCategoryIds.indexOf(2) < 0) {
    formData.value.fees.push({
      id: undefined,
      checkInId: formType === 'create' ? undefined : formData.value.id,
      feeCategoryId: 2,
      feeCategory: { categoryName: '护理费' },
      fee: 0,
      remark: '',
      operateType: 'new'
    })
  }
}

const handleSelectRestaurantCombo = (selectRestaurantCombo) => {
  formData.value.restaurantCombo = selectRestaurantCombo
  formData.value.restaurantComboId = selectRestaurantCombo.id

  const existsFeeCategoryIds = getKeyList(formData.value.fees, 'feeCategoryId')
  if (existsFeeCategoryIds.indexOf(3) < 0) {
    formData.value.fees.push({
      id: undefined,
      checkInId: formType === 'create' ? undefined : formData.value.id,
      feeCategoryId: 3,
      feeCategory: { categoryName: '餐饮费' },
      fee: 0,
      remark: '',
      operateType: 'new'
    })
  }
}

const handleSelectFeeCategory = (selectFeeCatetory) => {
  const existsFeeCategoryIds = getKeyList(formData.value.fees, 'feeCategoryId')
  selectFeeCatetory.forEach((fee) => {
    if (existsFeeCategoryIds.indexOf(fee.id) < 0) {
      formData.value.fees.push({
        id: undefined,
        checkInId: formType === 'create' ? undefined : formData.value.id,
        feeCategoryId: fee.id,
        feeCategory: { categoryName: fee.categoryName },
        fee: fee.fee,
        remark: '',
        operateType: 'new'
      })
    }
  })
}

const handleTableDblclick = (row) => {
  deleteFee(row)
}

const clickDeleteFee = () => {
  deleteFee(tableCurrentRow.value)
}

const deleteFee = (row) => {
  if (['1', '2', '3'].includes(row.feeCategoryId)) {
    message.error('内置费用不可删除')
  }
  const index = formData.value.fees.indexOf(row)
  formData.value.fees.splice(index, 1)
}

const calcNurseDetailFee = (nurseDetail: NursePlanDetail, beginTime: Date, endTime: Date) => {
  let nurseDetailFee = 0
  if (nurseDetail.execType == NursePlanExecTypeEnum.DAY) {
    const day = formatTime.betweenDay(beginTime, endTime)
    nurseDetailFee = nurseDetail.execTime.length * day * nurseDetail.item.itemFee
  } else if (nurseDetail.execType == NursePlanExecTypeEnum.WEEK) {
    const weekCount = dayjs(endTime).diff(beginTime, 'w')
    nurseDetailFee = nurseDetail.execTime.length * weekCount * nurseDetail.item.itemFee
    for (
      let tempBeginTime = dayjs(beginTime).add(weekCount, 'w');
      tempBeginTime.isBefore(endTime);
      tempBeginTime = tempBeginTime.add(1, 'd')
    ) {
      const week = tempBeginTime.day()
      if (nurseDetail.execFrequency.includes(week))
        nurseDetailFee += nurseDetail.execTime.length * nurseDetail.item.itemFee
    }
  } else if (nurseDetail.execType == NursePlanExecTypeEnum.XDAY) {
    const day = formatTime.betweenDay(beginTime, endTime)
    nurseDetailFee =
      Math.round(day / nurseDetail.execFrequency[0]) *
      nurseDetail.execTime.length *
      nurseDetail.item.itemFee
  } else {
    for (
      let tempBeginTime = dayjs(beginTime);
      tempBeginTime.isBefore(endTime);
      tempBeginTime = tempBeginTime.add(1, 'd')
    ) {
      if (nurseDetail.execFrequency.includes(tempBeginTime.date())) {
        nurseDetailFee += nurseDetail.execTime.length * nurseDetail.item.itemFee
      }
    }
  }
  return nurseDetailFee
}
</script>
